﻿using System.Collections.Generic;
using System.Text;
using Google.Apis.Translate.v2.Data;
using Google.Translates.Core.Entries;

namespace Google.Translates.Core
{
    public abstract class TranslatorByGoogle : TranslatorByHttp
    {
        protected string m_AppId;
        
        protected TranslatorByGoogle()
        {
            m_AppId = ApiSetting.GetGoogleTranslateAppId();
        }

        protected TranslatorByGoogle(int appIdIndex)
        {
            m_AppId = ApiSetting.GetGoogleTranslateAppId(appIdIndex);
        }

        /// <summary>
        /// 傳入一個長的句子,返回翻譯后的結果,過程中會有長句拆分成N個短句的過程
        /// </summary>
        /// <param name="longSentence"></param>
        /// <param name="srcLangKey"></param>
        /// <param name="trgLangKey"></param>
        /// <param name="autoCheckLangKey"></param>
        /// <param name="breakSentencesModelName"></param>
        /// <returns></returns>
        public string GetTranslationsByLongSentence(string longSentence, string srcLangKey, string trgLangKey,
                                                    ref string autoCheckLangKey, string breakSentencesModelName)
        {
            var splitKeyVals = new List<string>();
            List<string> lstShotSentence = null;
            if (breakSentencesModelName.Length == 0 ||
                breakSentencesModelName == StringHelper.Break_Sentences_Model_Mine)
                lstShotSentence = StringHelper.SplitSentence(longSentence, ref splitKeyVals);
            else if (breakSentencesModelName == StringHelper.Break_Sentences_Model_Bing)
            {
                longSentence = longSentence.Replace("\r\n", "").Replace("\r", "");
                lstShotSentence = new TranslatorByBingHttp().BreakSentences(longSentence, trgLangKey);
                splitKeyVals.Clear();
            }
            string[] ss = GetTranslations(lstShotSentence, splitKeyVals, srcLangKey, trgLangKey, ref autoCheckLangKey,
                                          breakSentencesModelName);
            var sb = new StringBuilder();
            foreach (string str in ss)
                sb.Append(str);
            return sb.ToString();
        }

        public string GetTranslationsByLongSentence(string longSentence, string srcLangKey, string trgLangKey)
        {
            string autoCheckLangKey = null;
            return GetTranslationsByLongSentence(longSentence, srcLangKey, trgLangKey, ref autoCheckLangKey, "");
        }

        public string GetTranslationsByLongSentence(string longSentence, string srcLangKey, string trgLangKey,
                                                    string breakSentencesModelName)
        {
            string autoCheckLangKey = null;
            return GetTranslationsByLongSentence(longSentence, srcLangKey, trgLangKey, ref autoCheckLangKey,
                                                 breakSentencesModelName);
        }

        public abstract object GetTranslations(List<string> shotSentence, string srcLangKey, string trgLangKey);

        /// <summary>
        /// 對N個短句進行Translate,返回Result(TranslationResult類型)
        /// </summary>
        /// <param name="shotSentence"></param>
        /// <param name="splitKeyVals"></param>
        /// <param name="srcLangKey"></param>
        /// <param name="trgLangKey"></param>
        /// <param name="autoCheckLangKey"></param>
        /// <param name="breakSentencesModelName"></param>
        /// <returns></returns>
        public string[] GetTranslations(List<string> shotSentence, List<string> splitKeyVals, string srcLangKey,
                                        string trgLangKey, ref string autoCheckLangKey, string breakSentencesModelName)
        {
            var needToTranslate = new List<string>(); //一個容器,放我們需要進行Translate的短句,不会提交重复的短句
            var indexMapping = new int[shotSentence.Count]; //記錄shotSentence每一個短句對應needToTranslate容量中哪一個元素
            var reVal = new string[shotSentence.Count]; //Translate后的結果,陣列的大小和順序與shotSentence一致
            for (int i = 0; i < shotSentence.Count; i++)
            {
                string transSrcVal = shotSentence[i];
                if (transSrcVal.Length > 0)
                {
                    int tempIndex = needToTranslate.IndexOf(transSrcVal);
                    if (tempIndex < 0)
                    {
                        if(transSrcVal.Trim().Length > 0)
                            needToTranslate.Add(transSrcVal); //發現需要Translate的短句,并加入needToTranslate的容器中
                        indexMapping[i] = needToTranslate.Count - 1;
                    }
                    else
                        indexMapping[i] = tempIndex;
                }
                else
                    indexMapping[i] = -1;
            }

            List<string> lstTrgSentences = GetTranslationsByEachTime(needToTranslate, 5, srcLangKey, trgLangKey,
                                                                     ref autoCheckLangKey);

            if (lstTrgSentences.Count == needToTranslate.Count)
            {
                for (int i = 0; i < indexMapping.Length; i++)
                {
                    if (indexMapping[i] > -1)
                        reVal[i] = lstTrgSentences[indexMapping[i]];
                    if (splitKeyVals.Count > i)
                        reVal[i] += splitKeyVals[i];
                }
            }

            return reVal;
        }

        /// <summary>
        /// 把N個短句分包Translate
        /// </summary>
        /// <param name="shotSentence"></param>
        /// <param name="transAmountEachTime"></param>
        /// <param name="srcLangKey"></param>
        /// <param name="trgLangKey"></param>
        /// <param name="autoCheckSrcLangKey"></param>
        /// <returns></returns>
        public List<string> GetTranslationsByEachTime(List<string> shotSentence, int transAmountEachTime,
                                                      string srcLangKey, string trgLangKey,
                                                      ref string autoCheckSrcLangKey)
        {
            var lstTrgSentences = new List<string>();
            var eachTranslateSources = new List<string>();
            int qValLen = 0;
            for (int i = 0; i < shotSentence.Count; i++)
            {
                string val = shotSentence[i];
                qValLen += val.Length;
                eachTranslateSources.Add(val);
                if ((i + 1)%transAmountEachTime == 0 || (i + 1) == shotSentence.Count)
                {
                    object obj = GetTranslations(eachTranslateSources, srcLangKey, trgLangKey);
                    if (obj != null)
                    {
                        if (obj is TranslationResult)
                        {
                            var eachResult = ((TranslationResult) obj);
                            foreach (TranslationItem trans in eachResult.Data.Translations)
                            {
                                lstTrgSentences.Add(trans.TranslatedText);
                                if (string.IsNullOrEmpty(autoCheckSrcLangKey))
                                    autoCheckSrcLangKey = trans.DetectedSourceLanguage;
                            }
                        }
                        else if (obj is TranslationsListResponse)
                        {
                            var eachResult = ((TranslationsListResponse) obj);
                            foreach (TranslationsResource trans in eachResult.Translations)
                            {
                                lstTrgSentences.Add(trans.TranslatedText);
                                if (string.IsNullOrEmpty(autoCheckSrcLangKey))
                                    autoCheckSrcLangKey = trans.DetectedSourceLanguage;
                            }
                        }
                        //Thread.Sleep(1000);
                    }


                    eachTranslateSources.Clear();
                }
            }
            return lstTrgSentences;
        }
    }
}